import com.thoughtworks.xstream.annotations.XStreamAlias
import com.thoughtworks.xstream.annotations.XStreamAsAttribute
import com.thoughtworks.xstream.XStream
import ru.niir.goodfil.db.handlers.Goodfil
import ru.niir.goodfil.db.Good
import ru.niir.goodfil.utils.PricelistItem
import ru.niir.goodfil.utils.FloatPrice
import ru.niir.goodfil.db.ClientGroup

//  Поискать идентификатор товара ИС по коду 1С
def long getGoodIdByCode(List<Good> goods, String code)
{
  for (Good g in goods)
    if (g.code == code)
      return g.id;
  return -1;
}

//  Поискать товар по коду ИС
def Good getGoodById(List<Good> goods, long id)
{
  for (Good g in goods)
    if (g.id == id)
      return g;
  return null;
}

/**
 *  Скрипт предназначен для загрузки прайса, выгруженного из 1С
 */

/*
  Итак, как работает загрузка прайса в GW?

  Модуль интеграции с 1С НЕ обрабатывает секцию "новые товары".
  Загрузку новых товаров осуществляет скрипт загрузки нового прайса (Price.xml).

  Как происходит загрузка прайса из Price.xml?

  1. Определяется соответствие колонок 1С номерам клиентских групп в 1С
  2. Исправляется латиница
  3. Создаем новые товары
  4. Очищаем прайс
  5. Загружаем прайс

  Что нужно вынести в пользовательский интерфейс:
  1. Путь к файлу
  2. Соответствие колонок

  Возможные итоги выполнения:
  1. Неправильно задано соответствие колонок
  2. 2 unrecoverable errors
 */

Goodfil gf = new Goodfil();
gf.createIfNotExists(".import.pricelist.path", "c:\\Price.xml", "Путь к файлу с выгруженным прайсом");
String FILENAME = gf.get(".import.pricelist.path");

@XStreamAlias("Rest")
class Rest
{
  @XStreamAsAttribute
  def String goodCode1C;

  @XStreamAsAttribute
  def String goodNameIC;

  @XStreamAsAttribute
  def String goodCodeIS;

  @XStreamAsAttribute
  def String brand;

  @XStreamAsAttribute
  def String prices;
}

@XStreamAlias("Document")
public class Document
{
  @XStreamAsAttribute
  def String type;

  @XStreamAlias("Rests")
  def List<Rest> rests;
}

XStream xs = new XStream();
xs.processAnnotations(Document.class);
xs.processAnnotations(Rest.class);

map = ["g_Колонка 1"     : 10,
       "g_Колонка 2"     : 9,
       "g_Колонка 3"     : 8,
       "g_Колонка 4"     : 7,
       "g_Колонка 5"     : 6,
       "g_Колонка 6"     : 11,
       "g_Закупочные"    : 12,
       "g_Мелкооптовые"  : 13,
       "g_Оптовые"       : 14,
       "g_Розничные"     : 15,

        "b_Закупочные"     : 18,
        "b_Колонка 1"     : 19,
        "b_Колонка 2"     : 20,
        "b_Колонка 3"     : 21,
        "b_Колонка 4"     : 22,
        "b_Колонка 5"     : 23,
        "b_Колонка 6"     : 24]

def String getBrandKey(Rest rest)
{
  if (rest.goodCodeIS.startsWith("AG"))
    int l = 5;
  
  if (rest.brand == "GoodWill")
    return "g_";
  if (rest.brand == "BIG")
    return "b_";
  return "";
}


List<Good> goods = gf.getGoods(0, Integer.MAX_VALUE, null);
List<ClientGroup> clientGroups = gf.getClientGroups();

//  Массив новых товаров
Set<Rest> new_goods = new HashSet();

//  Загрузили товары
Document document = (Document) xs.fromXML(new FileReader(FILENAME));


//  Проверяем корректность введенных клиентских групп
for (Rest rest in document.rests)
{
  rest.brand = rest.brand.trim();
  rest.goodCode1C = rest.goodCode1C.trim();
  rest.goodCodeIS = rest.goodCodeIS
                  .replaceAll("  ", " ")
                  .trim()
                  .toUpperCase()
                  .replaceAll("А", "A")
                  .replaceAll("В", "B")
                  .replaceAll("Е", "E")
                  .replaceAll("К", "K")
                  .replaceAll("М", "M")
                  .replaceAll("Н", "H")
                  .replaceAll("О", "O")
                  .replaceAll("Р", "P")
                  .replaceAll("С", "C")
                  .replaceAll("Т", "T")
                  .replaceAll("У", "Y")
                  .replaceAll("Х", "X");

  // Пропускаем товары, которых нет в ИС
  if (rest.goodCodeIS.isEmpty()) continue;

  String brandKey = getBrandKey(rest);
  if (brandKey == "") continue;

  String sClientGroup = rest.prices.split("=")[0].trim();
  if (!map.containsKey(brandKey + sClientGroup))
  {
    println "Bad clientgroup: ${sClientGroup}";
    System.exit 0;
  }
}

//  Формируем перечень новых для ИС товаров
for (Rest rest in document.rests)
{
  rest.goodCode1C = rest.goodCode1C.trim();
  rest.goodCodeIS = rest.goodCodeIS
                  .replaceAll("  ", " ")
                  .trim()
                  .toUpperCase()
                  .replaceAll("А", "A")
                  .replaceAll("В", "B")
                  .replaceAll("Е", "E")
                  .replaceAll("К", "K")
                  .replaceAll("М", "M")
                  .replaceAll("Н", "H")
                  .replaceAll("О", "O")
                  .replaceAll("Р", "P")
                  .replaceAll("С", "C")
                  .replaceAll("Т", "T")
                  .replaceAll("У", "Y")
                  .replaceAll("Х", "X");

  // Пропускаем товары, которых нет в ИС
  if (rest.goodCodeIS.isEmpty()) continue;

  //  Пропускаем товары без брэнда
  String brandKey = getBrandKey(rest);
  if (brandKey == "") continue;

  //  Если товар товый - добавляем его в массив новых
  if (getGoodIdByCode(goods, rest.goodCodeIS) == -1) new_goods << rest;
}

//
//  Сохраняем новые товары
//
println "Found new goods: ${new_goods.size()}";
for (new_good in new_goods.sort())
{
  println ".. ${new_good.goodCodeIS}";
}

//System.exit 0;

println "Saving new goods: ${new_goods.size()}";
for (new_good in new_goods.sort())
{
  println ".. ${new_good.goodCodeIS}";

  Good ng = new Good();
  ng.code       = new_good.goodCodeIS;
  ng.c1code     = new_good.goodCode1C;
  ng.name       = new_good.goodNameIC;
  ng.minPrice   = 1;  //  Минимальная цена
  ng.goodTypeId = 1;  // Корневая группа

  String brandKey = getBrandKey(new_good);
  if (brandKey == "g_") ng.brandId = 1;
  if (brandKey == "b_") ng.brandId = 2;

  try
  {
    gf.saveGood ng; //  Сохраняем товар
  }
  catch (Exception e)
  {
    println "....error: ${e}";
    System.exit(0);
  }
}

//
//  Очищаем прайс
//

gf.clearPricelist();

//  Старая реализация
//goods = gf.getGoods(0, Integer.MAX_VALUE, null);
//for (good in goods)
//{
//  PricelistItem pricelistItem = new PricelistItem(good);
//  for (clientGroup in clientGroups)
//  {
//    FloatPrice floatPrice = new FloatPrice(1);
//    floatPrice.setValue(0);
//    pricelistItem.put(clientGroup.getId(), floatPrice);
//  }
//  gf.updatePricelistItem(pricelistItem);
//}
println "Pricelist was cleaned!";

//  Загрузка прайса
for (Rest rest in document.rests)
{
  // Пропускаем товары, которых нет в ИС
  if (rest.goodCodeIS.isEmpty()) continue;

  //  Пропускаем товары без брэнда
  String brandKey = getBrandKey(rest);
  if (brandKey == "") continue;

  String sClientGroup = rest.prices.split("=")[0].trim();
  String sPrice = rest.prices.split("=")[1].trim();

  FloatPrice floatPrice = new FloatPrice(0);
  floatPrice.setValue(new Float(sPrice));

  long goodId = getGoodIdByCode(goods, rest.goodCodeIS);
  if (goodId == -1)
  {
    println "Unrecoverable error 1: ${goodId}, ${rest.goodCodeIS}";
    System.exit 1;
  }

  if (!map.containsKey(brandKey + sClientGroup))
  {
    println "Unrecoverable error 2: ${sClientGroup}";
    System.exit 2;
  }

  long clientgroupId = (Long) map[brandKey + sClientGroup];

  println "..${rest.goodCodeIS}"

  PricelistItem pricelistItem = new PricelistItem(getGoodById(goods, goodId));
  pricelistItem.put(clientgroupId, floatPrice);
  gf.updatePricelistItem(pricelistItem);
}

println "Finished";